﻿using ErrorOr;
using Gym.Domain.Common;
using Gym.Domain.Common.Entities;
using Gym.Domain.Common.ValueObjects;
using Gym.Domain.SessionAggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gym.Domain.ParticipantAggregate
{
    public class Participant : AggregateRoot
    {
        private readonly Schedule _schedule = Schedule.Empty();
        private readonly List<Guid> _sessionIds = new();
        public Guid UserId { get; }

        public IReadOnlyList<Guid> SessionIds => _sessionIds;

        public Participant(
        Guid userId,
        Schedule? schedule = null,
        Guid? id = null) : base(id ?? Guid.NewGuid())
        {
            UserId = userId;
            _schedule = schedule ?? Schedule.Empty();
        }

        public ErrorOr<Success> AddToSchedule(Session session)
        {
            if (_sessionIds.Contains(session.Id))
            {
                return Error.Conflict(description: "该课程已添加到该用户的课程计划中");
            }

            var bookTimeSlotResult = _schedule.BookTimeSlot(session.Date, session.Time);
            if (bookTimeSlotResult.IsError)
            {
                return bookTimeSlotResult.FirstError.Type == ErrorType.Conflict
                ? ParticipantErrors.CannotHaveTwoOrMoreOverlappingSessions
                : bookTimeSlotResult.Errors;
            }


            _sessionIds.Add(session.Id);
            return Result.Success;
        }

        public bool HasReservationForSession(Guid sessionId)
        {
            return _sessionIds.Contains(sessionId);
        }

        public bool IsTimeSlotFree(DateOnly date, TimeRange time)
        {
            return _schedule.CanBookTimeSlot(date, time);
        }

        public ErrorOr<Success> RemoveFromSchedule(Session session)
        {
            if (!_sessionIds.Contains(session.Id))
            {
                return Error.NotFound(description: "未在参与者日程中找到该课程");
            }

            var removeBookingResult = _schedule.RemoveBooking(
                session.Date,
                session.Time);

            if (removeBookingResult.IsError)
            {
                return removeBookingResult.Errors;
            }

            _sessionIds.Remove(session.Id);
            return Result.Success;
        }

        private Participant()
        {
        }
    }
}
